package com.globallogic.training.javase.university.schedule;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;

import org.apache.commons.lang.StringUtils;

import com.globallogic.training.javase.university.Speciality;
import com.globallogic.training.javase.university.member.Group;
import com.globallogic.training.javase.university.member.Teacher;
import com.globallogic.training.javase.university.subject.Activity;
import com.globallogic.training.javase.university.subject.ActivityType;
import com.globallogic.training.javase.university.subject.Subject;

/**
 * This class represents the Scheduler. The main purpose of the Scheduler is to
 * built a Schedule for one week.
 * 
 * @author Ivan Moisiienko
 * @version 0.2 2013/05/23
 */
public class Scheduler {

	private static final String SCHEDULER_PROPERTIES_FILE 
		= "scheduler.properties";
	private static final String SUBJECTS_FILE = "subjects.file";
	private static final String GROUPS_FILE = "groups.file";
	private static final String AUDITORIUMS_FILE = "auditoriums.file";
	private static final String SCHEDULE_FILE = "schedule.file";

	public static void main(String[] args) throws Exception {

		File file = null;

		InputStream is = Scheduler.class.getClassLoader().getResourceAsStream(
				SCHEDULER_PROPERTIES_FILE);

		Properties props = new Properties();
		props.load(is);
		is.close();

		file = new File(props.getProperty(AUDITORIUMS_FILE));
		Set<Auditorium> auds = readAuditoriums(file);

		file = new File(props.getProperty(GROUPS_FILE));
		Set<Group> groups = readGroups(file);

		file = new File(props.getProperty(SUBJECTS_FILE));
		Set<Subject> subjects = readSubjects(file);

		Set<Activity> allActivities = new LinkedHashSet<Activity>();
		int numberInPlan = 1;
		for (Group group : groups) {
			for (Subject subject : subjects) {

				Activity lecture = subject.createActivity(ActivityType.LECTURE,
						numberInPlan++, group);
				Activity seminar = subject.createActivity(ActivityType.SEMINAR,
						numberInPlan++, group);

				allActivities.add(lecture);
				allActivities.add(seminar);
			}
		}

		file = new File(props.getProperty(SCHEDULE_FILE));
		PrintWriter writer = new PrintWriter(file);

		Schedule schedule = Scheduler.buildSchedule(allActivities, auds);
		writeSchedule(writer, schedule, groups, subjects);
		writer.close();
	}

	public static Set<Auditorium> readAuditoriums(File file) throws IOException {
		Set<Auditorium> auditoriums = new TreeSet<Auditorium>();
		BufferedReader reader = new BufferedReader(new FileReader(file));

		String line = null;
		while ((line = reader.readLine()) != null) {
			String[] tokens = line.split("(\\s)*,(\\s)*");
			for (String token : tokens) {
				auditoriums.add(new Auditorium(token));
			}
		}

		reader.close();

		return auditoriums;
	}

	public static Set<Group> readGroups(File file) throws IOException {
		Set<Group> groups = new TreeSet<Group>();
		BufferedReader reader = new BufferedReader(new FileReader(file));

		String line = null;
		Speciality spec = new Speciality("Computer Science");
		while ((line = reader.readLine()) != null) {
			Group group = new Group(line);
			group.setSpeciality(spec);

			groups.add(group);
		}

		reader.close();

		return groups;
	}

	public static Set<Subject> readSubjects(File file) throws IOException {

		Set<Subject> subjects = new HashSet<Subject>();
		Set<String> subjectsTeachers = new TreeSet<String>();
		BufferedReader reader = new BufferedReader(new FileReader(file));

		String line = null;
		while ((line = reader.readLine()) != null) {
			subjectsTeachers.add(line);
		}

		reader.close();

		if (subjectsTeachers.size() == 0) {
			return null;
		}

		for (String s : subjectsTeachers) {
			Subject subject = new Subject(StringUtils.substringBefore(s, "-")
					.trim());
			String[] teachers = StringUtils.substringAfter(s, "-").trim()
					.split("(\\s)*,(\\s)*");

			for (int i = 0; i < teachers.length; i++) {
				subject.addTeacher(new Teacher(teachers[i]));
			}

			subjects.add(subject);
		}

		return subjects;
	}

	public static void writeSchedule(PrintWriter writer, Schedule schedule,
			Set<Group> groups, Set<Subject> subjects) throws SchedulerException {

		for (Group gr : groups) {
			writer.printf("%24s", gr.getGroupId());
		}

		for (DayOfWeek day : DayOfWeek.values()) {
			writer.println();
			writer.println(day.name());
			for (int i = 1; i <= Schedule.NUMBER_OF_CELLS_PER_DAY; i++) {

				writer.println(i);

				for (Group group : groups) {

					Activity activity = schedule.getActivity(day, i, group);
					Subject subject = (activity == null) ? null : activity
							.getSubject();

					writer.printf("|%25s", subject != null ? subject : "");
				}
				writer.println();

				for (Group g : groups) {

					Activity act = schedule.getActivity(day, i, g);
					writer.printf("|%25s", act != null ? act : "");
				}
				writer.println();

				for (Group g : groups) {

					Auditorium aud = schedule.getAuditorium(day, i, g);
					writer.printf("|%25s", aud != null ? aud : "");
				}
				writer.println("\n");
			}
		}

		writer.close();

	}

	public static Schedule buildSchedule(Set<Activity> activities,
			Set<Auditorium> auditoriums) {

		Schedule schedule = new Schedule();

		for (Activity activity : activities) {
			schedule.scheduleActivity(activity, auditoriums);
		}
		return schedule;
	}

}
